import jwt from 'jsonwebtoken';
import bcrypt from 'bcryptjs';
import dotenv from 'dotenv';
import { NextRequest, NextResponse } from 'next/server';
import { NextURL } from 'next/dist/server/web/next-url';
import { GloableResponseItem, ResponseEnum } from '@/utils/request/res';
import * as z from 'zod';
import 'reflect-metadata';

dotenv.config();

// HTTP方法元数据键
export const HTTP_METHOD_KEY = 'http:method';
export const HTTP_PATH_KEY = 'http:path';

export enum HttpMethod {
  GET = 'GET',
  POST = 'POST',
  PUT = 'PUT',
  DELETE = 'DELETE',
  PATCH = 'PATCH',
  OPTIONS = 'OPTIONS',
  HEAD = 'HEAD'
}

/**
 * HTTP方法装饰器工厂
 */
function createHttpMethodDecorator(method: HttpMethod) {
  return function (path?: string) {
    return function (
      target: any,
      propertyKey: string,
      descriptor: PropertyDescriptor
    ) {
      Reflect.defineMetadata(HTTP_METHOD_KEY, method, target, propertyKey);
      if (path) {
        Reflect.defineMetadata(HTTP_PATH_KEY, path, target, propertyKey);
      }
      return descriptor;
    };
  };
}

// 导出各种HTTP方法装饰器
export const GET = createHttpMethodDecorator(HttpMethod.GET);
export const POST = createHttpMethodDecorator(HttpMethod.POST);
export const PUT = createHttpMethodDecorator(HttpMethod.PUT);
export const DELETE = createHttpMethodDecorator(HttpMethod.DELETE);
export const PATCH = createHttpMethodDecorator(HttpMethod.PATCH);
export const OPTIONS = createHttpMethodDecorator(HttpMethod.OPTIONS);
export const HEAD = createHttpMethodDecorator(HttpMethod.HEAD);

interface DecodedToken {
  id: string;
  [key: string]: any;
}

// 扩展 NextApiRequest 接口
export interface ExtendedNextApiRequest extends NextRequest {
  user?: DecodedToken;
  geo: any;
  ip: string;
  nextUrl: NextURL;
  customBody?: any;
}

// 生成 JWT 的函数，设置失效时间
export function generateToken(payload: object): string {
  const expiresIn = parseInt(process.env.JWT_EXPIRES_IN as string, 10);
  const sanitizedPayload = JSON.parse(JSON.stringify(payload, (key, value) =>
    typeof value === 'bigint' ? value.toString() : value
  ));
  return jwt.sign(sanitizedPayload, process.env.JWT_SECRET as string, { expiresIn });
}

// 密码加密函数
export async function hashPassword(password: string): Promise<string> {
  const saltRounds = 10;
  return await bcrypt.hash(password, saltRounds);
}

// 密码验证函数
export async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return await bcrypt.compare(password, hash);
}

// 校验 JWT 是否超时
export function verifyToken(token: string): DecodedToken | null {
  try {
    return jwt.verify(token, process.env.JWT_SECRET as string) as DecodedToken;
  } catch (error) {
    if (error instanceof jwt.TokenExpiredError) {
      // console.log('Token expired');
    } else {
      // console.log('Token invalid');
    }
    return null;
  }
}

// 新增：提取 customBody 的共用方法
async function extractCustomBody(request: ExtendedNextApiRequest): Promise<any> {
  if (request.customBody) {
    return request.customBody;
  }
  const contentType = request.headers.get('contenttype') || request.headers.get('content-type') || request.headers.get('Content-Type') || '';
  if (contentType.includes('application/json')) {
    if (request.method === 'GET') {
      const url = new URL(request.url);
      const params = Object.fromEntries(url.searchParams.entries());
      request.customBody = params;
    } else {
      const textBody = await request.text();
      try {
        request.customBody = textBody ? JSON.parse(textBody) : {};
      } catch (e) {
        console.error('解析JSON失败:', e);
        request.customBody = {};
      }
    }
    return request.customBody;
  } else if (contentType.includes('multipart/form-data')) {
    // 处理文件上传
    try {
      const formData = await request.formData();
      const customBody: Record<string, any> = {};

      for (const [key, value] of formData.entries()) {
        customBody[key] = value;
      }

      request.customBody = customBody;
    } catch (error) {
      console.error('解析formData失败:', error);
      request.customBody = {};
    }
  }else{
    request.customBody = {};
  }
}

/**
 * 使用共用的 extractCustomBody 方法
 * @param request 
 * @returns 
 */
export function useCustomBody(request: ExtendedNextApiRequest): Promise<any> {
  return extractCustomBody(request);
}

// 登录校验
export function Auth() {
  return function (
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    const originalMethod = descriptor.value;
    descriptor.value = async function (request: ExtendedNextApiRequest, response: NextResponse) {
      try {
        const token = request.headers.get('authorization')?.split(' ')[1];
        if (!token) {
          return NextResponse.json({ error: '登录失效' }, { status: 401 });
        }
        const decoded = verifyToken(token);
        
        if (!decoded) {
          return NextResponse.json({ error: '登录失效' }, { status: 401 });
        }
        request.user = decoded;
        // 确保提取 customBody
        await extractCustomBody(request);
        return originalMethod.call(this, request, response);
      } catch (error) {
        return NextResponse.json({ error: '登录失效' }, { status: 401 });
      }
    };
    return descriptor;
  };
}

// 部门校验
export function Dept() {
  return function (
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    const originalMethod = descriptor.value;
    descriptor.value = async function (request: ExtendedNextApiRequest, response: NextResponse) {
      try {
        // 使用共用的 extractCustomBody 方法
        const customBody = await extractCustomBody(request);
        if (!customBody.dept_id) {
          return NextResponse.json({ error: '当前用户没有权限' }, { status: 401 });
        }
        if (typeof customBody.dept_id === "string") {
          customBody.dept_id = parseInt(customBody.dept_id || "0")
        }
        return originalMethod.call(this, request, response);
      } catch (error) {
        return NextResponse.json({ error: '当前用户没有权限' }, { status: 401 });
      }
    };
    return descriptor;
  };
}

// 统一返回格式
export function ResponseHandler() {
  return function (
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    const originalMethod = descriptor.value;
    descriptor.value = async function (request: ExtendedNextApiRequest, response: NextResponse) {
      try {
        // 确保提取 customBody
        await extractCustomBody(request);
        const result = await originalMethod.call(this, request, response);
        if (result instanceof NextResponse) {
          return result;
        }
        return GloableResponseItem(ResponseEnum.success, "操作成功", null);
      } catch (error) {
        if (error instanceof z.ZodError) {
          let msg = error.errors.map(err => err.message).join(',');
          return GloableResponseItem(ResponseEnum.fail, msg, null);
        } else {
          console.log("error====>>>>>", error);
          return GloableResponseItem(ResponseEnum.fail, "其他异常", null);
        }
      }
    };
    return descriptor;
  };
}

// 数据校验
export function DbScheme(schema: z.ZodSchema) {
  return function (
      target: any,
      propertyKey: string,
      descriptor: PropertyDescriptor
  ) {
      const originalMethod = descriptor.value;
      descriptor.value = async function (request: ExtendedNextApiRequest, response: NextResponse) {
          const customBody = await useCustomBody(request);
          const result = await schema.parse(customBody);
          if (result.error) {
              return NextResponse.json({ error: result.error.message }, { status: 400 });
          }
          return originalMethod.call(this, request, response);
      };
      return descriptor;
  };
}

// 日志记录装饰器（精简版）
export function LogOperation(options: {
  module: string;
  operationName: string; // 操作名称中可以包含业务类型，如"新增用户"、"删除机构"等
}) {
  return function (
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor
  ) {
    const originalMethod = descriptor.value;
    descriptor.value = async function (request: ExtendedNextApiRequest, response: NextResponse) {
      const startTime = new Date();
      let logData: any = {
        module: options.module,
        operation_name: options.operationName,
        request_method: request.method,
        operation_ip: request.ip || request.headers.get('x-forwarded-for') || request.headers.get('x-real-ip') || '127.0.0.1',
        status: 0,
        error_msg: null,
        operation_time: startTime
      };

      try {
        // 确保提取 customBody
        await extractCustomBody(request);
        
        // 记录用户信息
        if (request.user) {
          logData.user_id = parseInt(request.user.id);
          logData.user_name = request.user.user_name;
        }

        // 执行原方法
        const result = await originalMethod.call(this, request, response);
        
        // 计算耗时
        const endTime = new Date();
        logData.cost_time = endTime.getTime() - startTime.getTime();

        // 异步记录日志到数据库
        saveLogToDatabase(logData).catch(err => {
          console.error('保存日志失败:', err);
        });

        return result;
      } catch (error: any) {
        // 记录异常信息
        logData.status = 1;
        logData.error_msg = error.message || '系统异常';
        
        const endTime = new Date();
        logData.cost_time = endTime.getTime() - startTime.getTime();

        // 异步记录错误日志
        saveLogToDatabase(logData).catch(err => {
          console.error('保存错误日志失败:', err);
        });

        throw error;
      }
    };
    return descriptor;
  };
}



// 保存日志到数据库
async function saveLogToDatabase(logData: any) {
  try {
    const prisma = (await import('@/utils/db/PrismaService')).default;
    
    await prisma.sysLog.create({
      data: logData
    });
  } catch (error) {
    console.error('数据库保存日志失败:', error);
  }
}